home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 1 (Walnut Creek)
/
Aminet - June 1993 [Walnut Creek].iso
/
usenet
/
sources
/
volume2
/
editors
/
stevie.2
< prev
next >
Wrap
Text File
|
1988-12-02
|
36KB
|
1,470 lines
Path: xanth!mcnc!gatech!bloom-beacon!mit-eddie!ll-xn!adelie!infinet!ulowell!page
From: page@swan.ulowell.edu (Bob Page)
Newsgroups: comp.sources.amiga
Subject: v02i082: stevie - vi editor clone, Part02/04
Message-ID: <10420@swan.ulowell.edu>
Date: 2 Dec 88 01:43:28 GMT
Organization: University of Lowell, Computer Science Dept.
Lines: 1459
Approved: page@swan.ulowell.edu
Submitted-by: grwalter@watcgl.waterloo.edu
Posting-number: Volume 2, Issue 82
Archive-name: editors/stevie.2
# This is a shell archive.
# Remove everything above and including the cut line.
# Then run the rest of the file through sh.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar: Shell Archiver
# Run the following text with /bin/sh to create:
# keymap.h
# linefunc.c
# macros.h
# main.c
# mark.c
# misccmds.c
# param.c
# param.h
# raw.c
# This archive created: Thu Dec 1 20:37:28 1988
cat << \SHAR_EOF > keymap.h
/*
* STEVIE - Simply Try this Editor for VI Enthusiasts
*
* Code Contributions By : Tim Thompson twitch!tjt
* Tony Andrews onecom!wldrdg!tony
* G. R. (Fred) Walter watmath!watcgl!grwalter
*/
/*
* Keycode definitions for special keys
*
* On systems that have any of these keys, the routine 'inchar' in the
* machine-dependent code should return one of the codes here.
*/
#define K_CGRAVE 0x1e /* control grave accent */
#define K_HELP 0x80
#define K_UNDO 0x81
#define K_INSERT 0x82
#define K_HOME 0x83
#define K_UARROW 0x84
#define K_DARROW 0x85
#define K_LARROW 0x86
#define K_RARROW 0x87
#define K_SUARROW 0x88
#define K_SDARROW 0x89
#define K_SLARROW 0x8a
#define K_SRARROW 0x8b
#define K_F1 0x8c /* function keys */
#define K_F2 0x8d
#define K_F3 0x8e
#define K_F4 0x8f
#define K_F5 0x90
#define K_F6 0x91
#define K_F7 0x92
#define K_F8 0x93
#define K_F9 0x94
#define K_F10 0x95
#define K_SF1 0x96 /* shifted function keys */
#define K_SF2 0x97
#define K_SF3 0x98
#define K_SF4 0x99
#define K_SF5 0x9a
#define K_SF6 0x9b
#define K_SF7 0x9c
#define K_SF8 0x9d
#define K_SF9 0x9e
#define K_SF10 0x9f
SHAR_EOF
cat << \SHAR_EOF > linefunc.c
/*
* STEVIE - Simply Try this Editor for VI Enthusiasts
*
* Code Contributions By : Tim Thompson twitch!tjt
* Tony Andrews onecom!wldrdg!tony
* G. R. (Fred) Walter watmath!watcgl!grwalter
*/
#include "stevie.h"
/*
* nextline(curr)
*
* Return a pointer to the beginning of the next line after the one referenced
* by 'curr'. Return NULL if there is no next line (at EOF).
*/
LPTR *
nextline(curr)
LPTR *curr;
{
static LPTR next;
if (curr != NULL) {
if (curr->linep->next != Fileend->linep) {
next.index = 0;
next.linep = curr->linep->next;
return &next;
}
}
return (LPTR *) NULL;
}
/*
* prevline(curr)
*
* Return a pointer to the beginning of the line before the one referenced by
* 'curr'. Return NULL if there is no prior line.
*/
LPTR *
prevline(curr)
LPTR *curr;
{
static LPTR prev;
if (curr != NULL) {
if (curr->linep->prev != NULL) {
prev.index = 0;
prev.linep = curr->linep->prev;
return &prev;
}
}
return (LPTR *) NULL;
}
/*
* coladvance(p,col)
*
* Try to advance to the specified column, starting at p.
*/
LPTR *
coladvance(p, col)
LPTR *p;
int col;
{
static LPTR lp;
int c, in;
lp.linep = p->linep;
lp.index = p->index;
/* If we're on a blank ('\n' only) line, we can't do anything */
if (lp.linep->s[lp.index] == '\0')
return &lp;
/* try to advance to the specified column */
for (c = 0; col-- > 0; c++) {
/* Count a tab for what it's worth (if list mode not on) */
if (gchar(&lp) == TAB && !P(P_LS)) {
in = ((P(P_TS) - 1) - c % P(P_TS));
col -= in;
c += in;
}
/* Don't go past the end of */
/* the file or the line. */
if (inc(&lp)) {
dec(&lp);
break;
}
}
return &lp;
}
SHAR_EOF
cat << \SHAR_EOF > macros.h
/*
* STEVIE - Simply Try this Editor for VI Enthusiasts
*
* Code Contributions By : Tim Thompson twitch!tjt
* Tony Andrews onecom!wldrdg!tony
* G. R. (Fred) Walter watmath!watcgl!grwalter
*/
/*
* gchar(lp) - get the character at position "lp"
*/
#define gchar(lp) ((lp)->linep->s[(lp)->index])
/*
* pchar(lp, c) - put character 'c' at position 'lp'
*/
#define pchar(lp, c) ((lp)->linep->s[(lp)->index] = (c))
/*
* pswap(a, b) - swap two position pointers
*/
#define pswap(a, b) { LPTR pswaptmp; pswaptmp = a; a = b; b = pswaptmp; }
/*
* Position comparisons
*/
#define lt(a, b) ((LINEOF(a) != LINEOF(b)) \
? (LINEOF(a) < LINEOF(b)) : ((a)->index < (b)->index))
#define ltoreq(a, b) ((LINEOF(a) != LINEOF(b)) \
? (LINEOF(a) < LINEOF(b)) : ((a)->index <= (b)->index))
#define gt(a, b) ((LINEOF(a) != LINEOF(b)) \
? (LINEOF(a) > LINEOF(b)) : ((a)->index > (b)->index))
#define gtoreq(a, b) ((LINEOF(a) != LINEOF(b)) \
? (LINEOF(a) > LINEOF(b)) : ((a)->index >= (b)->index))
#define equal(a, b) (((a)->linep == (b)->linep) && ((a)->index == (b)->index))
/*
* anyinput
*
* Return non-zero if input is pending.
*/
#define anyinput() (Readbuffptr != NULL)
/*
* buf1line() - return TRUE if there is only one line in file buffer
*/
#define buf1line() (Filemem->linep->next == Fileend->linep)
/*
* bufempty() - return TRUE if the file buffer is empty
*/
#define bufempty() (buf1line() && Filemem->linep->s[0] == NUL)
/*
* lineempty() - return TRUE if the line is empty
*/
#define lineempty(p) ((p)->linep->s[0] == NUL)
/*
* startofline() - return TRUE if the given position is at start of line
*/
#define startofline(p) ((p)->index == 0)
/*
* endofline() - return TRUE if the given position is at end of line
*
* This routine will probably never be called with a position resting on the NUL
* byte, but handle it correctly in case it happens.
*/
#define endofline(p) \
((p)->linep->s[(p)->index] == NUL || (p)->linep->s[(p)->index + 1] == NUL)
/*
* RowNumber() - return the row number (if no UndoInProgress)
*/
#define RowNumber(p) (UndoInProgress ? 0 : cntllines(Filemem, (p)))
SHAR_EOF
cat << \SHAR_EOF > main.c
/*
* STEVIE - Simply Try this Editor for VI Enthusiasts
*
* Code Contributions By : Tim Thompson twitch!tjt
* Tony Andrews onecom!wldrdg!tony
* G. R. (Fred) Walter watmath!watcgl!grwalter
*/
#include "stevie.h"
int Rows; /* Number of Rows and Columns */
int Columns; /* in the current window. */
char *Realscreen = NULL; /* What's currently on the screen, a
* single array of size Rows*Columns. */
char *Nextscreen = NULL; /* What's to be put on the screen. */
char *Filename = NULL;/* Current file name */
LPTR *Filemem; /* The contents of the file, as a single
* array. */
LPTR *Fileend; /* Pointer to the end of the file in Filemem.
* (It points to the byte AFTER the last
* byte.) */
LPTR *Topchar; /* Pointer to the byte in Filemem which is in
* the upper left corner of the screen. */
LPTR *Botchar; /* Pointer to the byte in Filemem which is
* just off the bottom of the screen. */
LPTR *Curschar; /* Pointer to byte in Filemem at which the
* cursor is currently placed. */
int Curscol; /* Current position of cursor (column) */
int Cursrow; /* Current position of cursor (row) */
int Cursvcol; /* Current virtual column, the column number
* of the file's actual line, as opposed to
* the column number we're at on the screen.
* This makes a difference on lines that span
* more than one screen line. */
int Curswant = 0; /* The column we'd like to be at. This is
* used try to stay in the same column
* through up/down cursor motions. */
bool_t set_want_col; /* If set, then update Curswant the next time
* through cursupdate() to the current
* virtual column. */
int State = NORMAL; /* This is the current state of the command
* interpreter. */
int Prenum = 0; /* The (optional) number before a command. */
LPTR *Insstart; /* This is where the latest insert/append
* mode started. */
bool_t Changed = FALSE;/* Set to TRUE if something in the file has
* been changed and not written out. */
char *IObuff; /* file reads are done, one line at a time,
* into this buffer; as well as sprintf's */
char *Insbuffptr = NULL;
char *Insbuff; /* Each insertion gets stuffed into this
* buffer. */
char *Readbuffptr = NULL;
char *Readbuff; /* Having this buffer allows STEVIE to easily
* make itself do commands */
char *Redobuffptr = NULL;
char *Redobuff; /* Each command should stuff characters into
* this buffer that will re-execute itself. */
bool_t UndoInProgress = FALSE; /* Set to TRUE if undo'ing */
char *Undobuffptr = NULL;
char *Undobuff; /* Each command should stuff characters into
* this buffer that will undo its effects. */
char *UndoUndobuffptr = NULL;
char *UndoUndobuff; /* Each command should stuff characters into
* this buffer that will undo its undo. */
char *Yankbuffptr = NULL;
char *Yankbuff; /* Yank buffer */
char last_command = NUL; /* last command */
char last_command_char = NUL; /* character needed to undo
* last command */
bool_t RedrawingDisabled = FALSE; /* Set to TRUE if undo'ing or
* put'ing */
bool_t MustRedrawLine = FALSE; /* Set to TRUE if we must redraw the
* current line */
bool_t MustRedrawScreen = TRUE; /* Set to TRUE if we must
* redraw the screen */
char **files; /* list of input files */
int numfiles; /* number of input files */
int curfile; /* number of the current file */
static void
usage()
{
fprintf(stderr, "usage: stevie [file ...]\n");
fprintf(stderr, " stevie -t tag\n");
fprintf(stderr, " stevie +[num] file\n");
fprintf(stderr, " stevie +/pat file\n");
exit(1);
}
#ifdef AMIGA
void
#else
int
#endif
main(argc, argv)
int argc;
char **argv;
{
char *initstr, *getenv(); /* init string from the environment */
char *tag = NULL; /* tag from command line */
char *pat = NULL; /* pattern from command line */
int line = -1; /* line number from command line */
int atoi();
#ifdef AMIGA
/*
* This won't be needed if you have a version of Lattice 4.01 without broken
* break signal handling.
*/
(void) signal(SIGINT, SIG_IGN);
#endif
/*
* Process the command line arguments.
*/
if (argc > 1) {
switch (argv[1][0]) {
case '-': /* -t tag */
if (argv[1][1] != 't')
usage();
if (argv[2] == NULL)
usage();
Filename = NULL;
tag = argv[2];
numfiles = 1;
break;
case '+': /* +n or +/pat */
if (argv[1][1] == '/') {
if (argv[2] == NULL)
usage();
Filename = strsave(argv[2]);
pat = &(argv[1][1]);
numfiles = 1;
} else if (isdigit(argv[1][1]) || argv[1][1] == NUL) {
if (argv[2] == NULL)
usage();
Filename = strsave(argv[2]);
numfiles = 1;
line = (isdigit(argv[1][1])) ?
atoi(&(argv[1][1])) : 0;
} else
usage();
break;
default: /* must be a file name */
Filename = strsave(argv[1]);
files = &(argv[1]);
numfiles = argc - 1;
break;
}
} else {
Filename = NULL;
numfiles = 1;
}
curfile = 0;
windinit();
/*
* Allocate LPTR structures for all the various position pointers
*/
if ((Filemem = (LPTR *) malloc((unsigned) sizeof(LPTR))) == NULL) {
fprintf(stderr, "Can't allocate data structures\n");
windexit(0);
}
if ((Fileend = (LPTR *) malloc((unsigned) sizeof(LPTR))) == NULL) {
fprintf(stderr, "Can't allocate data structures\n");
windexit(0);
}
if ((Topchar = (LPTR *) malloc((unsigned) sizeof(LPTR))) == NULL) {
fprintf(stderr, "Can't allocate data structures\n");
windexit(0);
}
if ((Botchar = (LPTR *) malloc((unsigned) sizeof(LPTR))) == NULL) {
fprintf(stderr, "Can't allocate data structures\n");
windexit(0);
}
if ((Curschar = (LPTR *) malloc((unsigned) sizeof(LPTR))) == NULL) {
fprintf(stderr, "Can't allocate data structures\n");
windexit(0);
}
if ((Insstart = (LPTR *) malloc((unsigned) sizeof(LPTR))) == NULL) {
fprintf(stderr, "Can't allocate data structures\n");
windexit(0);
}
/*
* Allocate space for the many buffers
*/
if ((IObuff = malloc(IOSIZE)) == NULL) {
fprintf(stderr, "Can't allocate data structures\n");
windexit(0);
}
if ((Insbuff = malloc(INSERT_SIZE)) == NULL) {
fprintf(stderr, "Can't allocate data structures\n");
windexit(0);
}
if ((Readbuff = malloc(READSIZE)) == NULL) {
fprintf(stderr, "Can't allocate data structures\n");
windexit(0);
}
if ((Redobuff = malloc(REDO_UNDO_SIZE)) == NULL) {
fprintf(stderr, "Can't allocate data structures\n");
windexit(0);
}
if ((Undobuff = malloc(REDO_UNDO_SIZE)) == NULL) {
fprintf(stderr, "Can't allocate data structures\n");
windexit(0);
}
if ((UndoUndobuff = malloc(REDO_UNDO_SIZE)) == NULL) {
fprintf(stderr, "Can't allocate data structures\n");
windexit(0);
}
if ((Yankbuff = malloc(YANKSIZE)) == NULL) {
fprintf(stderr, "Can't allocate data structures\n");
windexit(0);
}
screenalloc();
filealloc(); /* Initialize Filemem & Fileend */
screenclear();
if ((initstr = getenv("EXINIT")) != NULL) {
char *lp, buf[128];
if ((lp = getenv("LINES")) != NULL) {
sprintf(buf, "%s lines=%s", initstr, lp);
readcmdline(':', buf);
} else
readcmdline(':', initstr);
}
if (Filename != NULL) {
if (readfile(Filename, Filemem, FALSE))
filemess("[New File]");
} else
msg("Empty Buffer");
setpcmark();
updateNextscreen();
if (tag) {
stuffReadbuff(":ta ");
stuffReadbuff(tag);
stuffReadbuff("\n");
} else if (pat) {
stuffReadbuff(pat);
stuffReadbuff("\n");
} else if (line >= 0) {
if (line > 0)
stuffnumReadbuff(line);
stuffReadbuff("G");
}
edit();
windexit(0);
}
void
stuffReadbuff(s)
char *s;
{
if (strlen(s) == 0)
return;
if (Readbuffptr == NULL) {
if ((strlen(s) + 1) < READSIZE) {
strcpy(Readbuff, s);
Readbuffptr = Readbuff;
} else
emsg("Couldn't stuffReadbuff() - should never happen");
} else if ((strlen(Readbuff) + (strlen(s) + 1)) < READSIZE)
strcat(Readbuff, s);
else
emsg("Couldn't stuffReadbuff() - should never happen");
}
void
stuffnumReadbuff(n)
int n;
{
char buf[32];
sprintf(buf, "%d", n);
stuffReadbuff(buf);
}
/* OPTRESULT */
char
vgetc()
{
if (Readbuffptr != NULL) {
char nextc = *Readbuffptr++;
if (*Readbuffptr == NUL) {
*Readbuff = NUL;
Readbuffptr = NULL;
}
return (nextc);
}
return (inchar());
}
char
vpeekc()
{
if (Readbuffptr != NULL)
return (*Readbuffptr);
return (NUL);
}
SHAR_EOF
cat << \SHAR_EOF > mark.c
/*
* STEVIE - Simply Try this Editor for VI Enthusiasts
*
* Code Contributions By : Tim Thompson twitch!tjt
* Tony Andrews onecom!wldrdg!tony
* G. R. (Fred) Walter watmath!watcgl!grwalter
*/
#include "stevie.h"
#ifdef MEGAMAX
overlay "mark"
#endif
/*
* This file contains routines to maintain and manipulate marks.
*/
#define NMARKS 10 /* max. # of marks that can be saved */
struct mark {
char name;
LPTR pos;
};
static struct mark mlist[NMARKS];
static struct mark pcmark; /* previous context mark */
static bool_t pcvalid = FALSE;/* true if pcmark is valid */
/*
* setmark(c) - set mark 'c' at current cursor position
*
* Returns TRUE on success, FALSE if no room for mark or bad name given.
*/
bool_t
setmark(c)
char c;
{
int i;
if (!isalpha(c))
return FALSE;
/*
* If there is already a mark of this name, then just use the existing
* mark entry.
*/
for (i = 0; i < NMARKS; i++) {
if (mlist[i].name == c) {
mlist[i].pos = *Curschar;
return TRUE;
}
}
/*
* There wasn't a mark of the given name, so find a free slot
*/
for (i = 0; i < NMARKS; i++) {
if (mlist[i].name == NUL) { /* got a free one */
mlist[i].name = c;
mlist[i].pos = *Curschar;
return TRUE;
}
}
return FALSE;
}
/*
* setpcmark() - set the previous context mark to the current position
*/
void
setpcmark()
{
pcmark.pos = *Curschar;
pcvalid = TRUE;
}
/*
* getmark(c) - find mark for char 'c'
*
* Return pointer to LPTR or NULL if no such mark.
*/
LPTR *
getmark(c)
char c;
{
int i;
if (c == '\'' || c == '`') /* previous context mark */
return pcvalid ? &(pcmark.pos) : (LPTR *) NULL;
for (i = 0; i < NMARKS; i++) {
if (mlist[i].name == c)
return &(mlist[i].pos);
}
return (LPTR *) NULL;
}
/*
* clrall() - clear all marks
*
* Used mainly when trashing the entire buffer during ":e" type commands
*/
void
clrall()
{
int i;
for (i = 0; i < NMARKS; i++)
mlist[i].name = NUL;
pcvalid = FALSE;
}
/*
* clrmark(line) - clear any marks for 'line'
*
* Used any time a line is deleted so we don't have marks pointing to
* non-existent lines.
*/
void
clrmark(line)
LINE *line;
{
int i;
for (i = 0; i < NMARKS; i++) {
if (mlist[i].pos.linep == line)
mlist[i].name = NUL;
}
if (pcvalid && (pcmark.pos.linep == line))
pcvalid = FALSE;
}
SHAR_EOF
cat << \SHAR_EOF > misccmds.c
/*
* STEVIE - Simply Try this Editor for VI Enthusiasts
*
* Code Contributions By : Tim Thompson twitch!tjt
* Tony Andrews onecom!wldrdg!tony
* G. R. (Fred) Walter watmath!watcgl!grwalter
*/
#include "stevie.h"
static bool_t
openfwd(), openbwd();
extern int did_ai;
/*
* opencmd
*
* Add a blank line above or below the current line.
*/
bool_t
opencmd(dir, can_ai)
int dir;
int can_ai; /* if true, consider auto-indent */
{
if (dir == FORWARD)
return (openfwd(can_ai));
else
return (openbwd(can_ai));
}
static bool_t
openfwd(can_ai)
int can_ai;
{
LINE *l;
LPTR *next;
char *s; /* string to be moved to new line, if any */
/*
* If we're in insert mode, we need to move the remainder of the current
* line onto the new line. Otherwise the new line is left blank.
*/
if (State == INSERT)
s = &Curschar->linep->s[Curschar->index];
else
s = "";
if ((next = nextline(Curschar)) == NULL) /* open on last line */
next = Fileend;
/*
* By asking for as much space as the prior line had we make sure that
* we'll have enough space for any auto-indenting.
*/
if ((l = newline(strlen(Curschar->linep->s) + SLOP)) == NULL) {
emsg("out of memory");
beep();
sleep(2);
return (FALSE);
}
if (*s != NUL)
strcpy(l->s, s); /* copy string to new line */
#ifdef AUTO_INDENT
else if (can_ai && P(P_AI)) {
/*
* Auto-indent removed due to buggy implementation...
*/
did_ai = TRUE;
}
#endif
if (State == INSERT) /* truncate current line at cursor */
*s = NUL;
Curschar->linep->next = l; /* link neighbors to new line */
next->linep->prev = l;
l->prev = Curschar->linep; /* link new line to neighbors */
l->next = next->linep;
if (next == Fileend) /* new line at end */
l->num = Curschar->linep->num + LINEINC;
else if ((l->prev->num) + 1 == l->next->num) /* no gap, renumber */
renum();
else { /* stick it in the middle */
long lnum;
lnum = (l->prev->num + l->next->num) / 2;
l->num = lnum;
}
*Curschar = *nextline(Curschar); /* cursor moves down */
Curschar->index = 0;
s_ins(Cursrow + 1, 1); /* insert a physical line */
updateNextscreen(); /* because Botchar is now invalid */
cursupdate(); /* update Cursrow before insert */
return (TRUE);
}
static bool_t
openbwd(can_ai)
int can_ai;
{
LINE *l;
LPTR *prev;
prev = prevline(Curschar);
if ((l = newline(strlen(Curschar->linep->s) + SLOP)) == NULL) {
emsg("out of memory");
beep();
sleep(2);
return (FALSE);
}
Curschar->linep->prev = l; /* link neighbors to new line */
if (prev != NULL)
prev->linep->next = l;
l->next = Curschar->linep; /* link new line to neighbors */
if (prev != NULL)
l->prev = prev->linep;
#ifdef AUTO_INDENT
if (can_ai && P(P_AI)) {
/*
* Auto-indent removed due to buggy implementation...
*/
did_ai = TRUE;
}
#endif
*Curschar = *prevline(Curschar); /* cursor moves up */
Curschar->index = 0;
if (prev == NULL) /* new start of file */
Filemem->linep = l;
renum(); /* keep it simple - we don't do this often */
cursupdate(); /* update Cursrow before insert */
if (Cursrow != 0)
s_ins(Cursrow, 1); /* insert a physical line */
updateNextscreen();
return (TRUE);
}
int
cntllines(pbegin, pend)
LPTR *pbegin, *pend;
{
register LINE *lp;
register int lnum = 1;
for (lp = pbegin->linep; lp != pend->linep; lp = lp->next)
lnum++;
return (lnum);
}
/*
* plines(p) - return the number of physical screen lines taken by line 'p'
*/
int
plines(p)
LPTR *p;
{
int col;
char *s;
if (p == NULL) {
fprintf(stderr, "plines(p) : p == NULL ????");
return (0);
}
s = p->linep->s;
if (*s == NUL) /* empty line */
return 1;
/*
* If list mode is on, then the '$' at the end of the line takes up one
* extra column.
*/
col = P(P_LS) ? 1 : 0;
for (; *s != NUL; s++) {
if (*s == TAB && !P(P_LS))
col += P(P_TS) - (col % P(P_TS));
else
col += chars[*s].ch_size;
}
return ((col + (Columns - 1)) / Columns);
}
void
fileinfo()
{
long l1, l2;
char buf[MAX_COLUMNS + 1];
if (bufempty()) {
msg("Buffer Empty");
return;
}
l1 = cntllines(Filemem, Curschar);
l2 = cntllines(Filemem, Fileend) - 1;
sprintf(buf, "\"%s\"%s line %ld of %ld -- %ld %% --",
(Filename != NULL) ? Filename : "No File",
Changed ? " [Modified]" : "",
l1, l2, (l1 * 100) / l2);
msg(buf);
}
/*
* gotoline(n) - return a pointer to line 'n'
*
* Returns a pointer to the last line of the file if n is zero, or beyond the
* end of the file.
*/
LPTR *
gotoline(n)
int n;
{
static LPTR l;
l.index = 0;
if (n == 0)
l = *prevline(Fileend);
else {
LPTR *p;
for (l = *Filemem; --n > 0; l = *p)
if ((p = nextline(&l)) == NULL)
break;
}
return &l;
}
void
inschar(c)
char c;
{
char *p;
char *pend;
/* make room for the new char. */
if (!canincrease(1))
return;
p = &Curschar->linep->s[strlen(Curschar->linep->s) + 1];
pend = &Curschar->linep->s[Curschar->index];
for (; p > pend; p--)
*p = *(p - 1);
*p = c;
if (RedrawingDisabled) {
inc(Curschar);
return;
}
/*
* If we're in insert mode and showmatch mode is set, then check for
* right parens and braces. If there isn't a match, then beep. If there
* is a match AND it's on the screen, then flash to it briefly. If it
* isn't on the screen, don't do anything.
*/
if (P(P_SM) && State == INSERT && (c == ')' || c == '}' || c == ']')) {
LPTR *lpos, csave;
if ((lpos = showmatch()) == NULL) /* no match, so beep */
beep();
else if (LINEOF(lpos) >= LINEOF(Topchar)) {
updateNextscreen(); /* show the new char first */
updateRealscreen();
csave = *Curschar;
*Curschar = *lpos; /* move to matching char */
cursupdate();
windgoto(Cursrow, Curscol);
delay(); /* brief pause */
*Curschar = csave; /* restore cursor position */
cursupdate();
}
}
inc(Curschar);
}
void
insstr(s)
char *s;
{
char *p, *endp;
int k, n = strlen(s);
/* Move everything in the file over to make */
/* room for the new string. */
if (!canincrease(n))
return;
endp = &Curschar->linep->s[Curschar->index];
p = Curschar->linep->s + strlen(Curschar->linep->s) + 1 + n;
for (; p > endp; p--)
*p = *(p - n);
p = &Curschar->linep->s[Curschar->index];
for (k = 0; k < n; k++) {
*p++ = *s++;
inc(Curschar);
}
}
bool_t
delchar(fixpos, undo)
bool_t fixpos; /* if TRUE fix the cursor position when done */
bool_t undo; /* if TRUE put char deleted into Undo buffer */
{
int i;
/* Check for degenerate case; there's nothing in the file. */
if (bufempty())
return FALSE;
if (lineempty(Curschar)) /* can't do anything */
return FALSE;
if (undo)
AppendToUndobuff(mkstr(gchar(Curschar)));
/* Delete the char. at Curschar by shifting everything in the line down. */
for (i = Curschar->index + 1; i < Curschar->linep->size; i++)
Curschar->linep->s[i - 1] = Curschar->linep->s[i];
/*
* If we just took off the last character of a non-blank line, we don't
* want to end up positioned at the newline.
*/
if (fixpos) {
if (gchar(Curschar) == NUL && Curschar->index > 0 && State != INSERT)
Curschar->index--;
}
return TRUE;
}
void
delline(nlines)
{
LINE *p, *q;
int doscreen = TRUE; /* if true, update the screen */
/*
* There's no point in keeping the screen updated if we're deleting more
* than a screen's worth of lines.
*/
if (nlines > (Rows - 1)) {
doscreen = FALSE;
s_del(Cursrow, Rows - 1); /* flaky way to clear rest of screen */
}
while (nlines-- > 0) {
if (bufempty()) /* nothing to delete */
break;
if (buf1line()) { /* just clear the line */
Curschar->linep->s[0] = NUL;
Curschar->index = 0;
break;
}
p = Curschar->linep->prev;
q = Curschar->linep->next;
if (p == NULL) { /* first line of file so... */
Filemem->linep = q; /* adjust start of file */
Topchar->linep = q; /* and screen */
} else
p->next = q;
q->prev = p;
clrmark(Curschar->linep); /* clear marks for the line */
/*
* Delete the correct number of physical lines on the screen
*/
if (doscreen)
s_del(Cursrow, plines(Curschar));
/*
* If deleting the top line on the screen, adjust Topchar
*/
if (Topchar->linep == Curschar->linep)
Topchar->linep = q;
free(Curschar->linep->s);
free((char *) (Curschar->linep));
Curschar->linep = q;
Curschar->index = 0; /* is this right? */
/* If we delete the last line in the file, back up */
if (Curschar->linep == Fileend->linep) {
Curschar->linep = Curschar->linep->prev;
/* and don't try to delete any more lines */
break;
}
}
}
SHAR_EOF
cat << \SHAR_EOF > param.c
/*
* STEVIE - Simply Try this Editor for VI Enthusiasts
*
* Code Contributions By : Tim Thompson twitch!tjt
* Tony Andrews onecom!wldrdg!tony
* G. R. (Fred) Walter watmath!watcgl!grwalter
*/
/*
* Code to handle user-settable parameters. This is all pretty much table-
* driven. To add a new parameter, put it in the params array, and add a
* macro for it in param.h. If it's a numeric parameter, add any necessary
* bounds checks to doset(). String parameters aren't currently supported.
*/
#include "stevie.h"
struct param params[] = {
{"tabstop", "ts", 8, P_NUM},
{"scroll", "scroll", 12, P_NUM},
{"report", "report", 5, P_NUM},
{"lines", "lines", 25, P_NUM},
{"vbell", "vb", TRUE, P_BOOL},
{"showmatch", "sm", FALSE, P_BOOL},
{"wrapscan", "ws", TRUE, P_BOOL},
{"errorbells", "eb", FALSE, P_BOOL},
{"showmode", "mo", FALSE, P_BOOL},
{"backup", "bk", FALSE, P_BOOL},
{"return", "cr", TRUE, P_BOOL},
{"list", "list", FALSE, P_BOOL},
{"autoindent", "ai", FALSE, P_BOOL},
{"", "", 0, 0,} /* end marker */
};
static void showparms();
void
doset(arg, inter)
char *arg; /* parameter string */
bool_t inter; /* TRUE if called interactively */
{
int i;
char *s;
bool_t did_lines = FALSE;
bool_t state = TRUE; /* new state of boolean parms. */
if (arg == NULL) {
showparms(FALSE);
return;
}
if (strncmp(arg, "all", 3) == 0) {
showparms(TRUE);
return;
}
if (strncmp(arg, "no", 2) == 0) {
state = FALSE;
arg += 2;
}
for (i = 0; params[i].fullname[0] != NUL; i++) {
s = params[i].fullname;
if (strncmp(arg, s, strlen(s)) == 0) /* matched full name */
break;
s = params[i].shortname;
if (strncmp(arg, s, strlen(s)) == 0) /* matched short name */
break;
}
if (params[i].fullname[0] != NUL) { /* found a match */
if (params[i].flags & P_NUM) {
did_lines = (i == P_LI);
if (inter && (arg[strlen(s)] != '=' || state == FALSE))
emsg("Invalid set of numeric parameter");
else {
params[i].value = atoi(arg + strlen(s) + 1);
params[i].flags |= P_CHANGED;
}
} else { /* boolean */
if (inter && (arg[strlen(s)] == '='))
emsg("Invalid set of boolean parameter");
else {
params[i].value = state;
params[i].flags |= P_CHANGED;
}
}
} else {
if (inter)
emsg("Unrecognized 'set' option");
}
/*
* Update the screen in case we changed something like "tabstop" or
* "list" that will change its appearance.
*/
if (inter)
updateNextscreen();
if (did_lines) {
Rows = P(P_LI);
screenalloc(); /* allocate new screen buffers */
screenclear();
updateNextscreen();
}
/*
* Check the bounds for numeric parameters here
*/
if (P(P_TS) <= 0 || P(P_TS) > 32) {
if (inter)
emsg("Invalid tab size specified");
P(P_TS) = 8;
return;
}
if (P(P_SS) <= 0 || P(P_SS) > Rows) {
if (inter)
emsg("Invalid scroll size specified");
P(P_SS) = 12;
return;
}
/*
* Check for another argument, and call doset() recursively, if found. If
* any argument results in an error, no further parameters are processed.
*/
while (*arg != ' ' && *arg != '\t') { /* skip to next white space */
if (*arg == NUL)
return; /* end of parameter list */
arg++;
}
while (*arg == ' ' || *arg == '\t') /* skip to next non-white */
arg++;
if (*arg)
doset(arg, TRUE); /* recurse on next parameter, if present */
}
static void
showparms(all)
bool_t all; /* show ALL parameters */
{
struct param *p;
char buf[64];
gotocmdline(YES, NUL);
outstr("Parameters:\r\n");
for (p = ¶ms[0]; p->fullname[0] != NUL; p++) {
if (!all && ((p->flags & P_CHANGED) == 0))
continue;
if (p->flags & P_BOOL)
sprintf(buf, "\t%s%s\r\n",
(p->value ? "" : "no"), p->fullname);
else
sprintf(buf, "\t%s=%d\r\n", p->fullname, p->value);
outstr(buf);
}
wait_return();
}
SHAR_EOF
cat << \SHAR_EOF > param.h
/*
* STEVIE - Simply Try this Editor for VI Enthusiasts
*
* Code Contributions By : Tim Thompson twitch!tjt
* Tony Andrews onecom!wldrdg!tony
* G. R. (Fred) Walter watmath!watcgl!grwalter
*/
/*
* Settable parameters
*/
struct param {
char *fullname; /* full parameter name */
char *shortname; /* permissible abbreviation */
int value; /* parameter value */
int flags;
};
extern struct param params[];
/*
* Flags
*/
#define P_BOOL 0x01 /* the parameter is boolean */
#define P_NUM 0x02 /* the parameter is numeric */
#define P_CHANGED 0x04 /* the parameter has been changed */
/*
* The following are the indices in the params array for each parameter
*/
/*
* Numeric parameters
*/
#define P_TS 0 /* tab size */
#define P_SS 1 /* scroll size */
#define P_RP 2 /* report */
#define P_LI 3 /* lines */
/*
* Boolean parameters
*/
#define P_VB 4 /* visual bell */
#define P_SM 5 /* showmatch */
#define P_WS 6 /* wrap scan */
#define P_EB 7 /* error bells */
#define P_MO 8 /* show mode */
#define P_BK 9 /* make backups when writing out files */
#define P_CR 10 /* use cr-lf to terminate lines on writes */
#define P_LS 11 /* show tabs and newlines graphically */
#define P_AI 12 /* auto-indent */
/*
* Macro to get the value of a parameter
*/
#define P(n) (params[n].value)
SHAR_EOF
cat << \SHAR_EOF > raw.c
/*
* raw.c
*
* This is a routine for setting a given stream to raw or cooked mode on the
* Amiga . This is useful when you are using Lattice C to produce programs
* that want to read single characters with the "getch()" or "fgetc" call.
*
* Written : 18-Jun-87 By Chuck McManis.
*/
#include <exec/types.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <stdio.h>
#include <ios1.h>
#include <error.h>
extern int errno; /* The error variable */
/*
* Function raw() - Convert the specified file pointer to 'raw' mode. This
* only works on TTY's and essentially keeps DOS from translating keys for
* you, also (BIG WIN) it means getch() will return immediately rather than
* wait for a return. You lose editing features though.
*/
long
raw(fp)
FILE *fp;
{
struct MsgPort *mp; /* The File Handle message port */
struct FileHandle *afh;
struct UFB *ufb;
long Arg[1], res;
ufb = (struct UFB *) chkufb(fileno(fp)); /* Step one, get the file
* handle */
afh = (struct FileHandle *) (ufb->ufbfh);
if (!IsInteractive(afh)) { /* Step two, check to see if it's a console */
errno = ENOTTY;
return (-1);
}
/* Step three, get it's message port. */
mp = ((struct FileHandle *) (BADDR(afh)))->fh_Type;
Arg[0] = -1L;
res = SendPacket(mp, ACTION_SCREEN_MODE, Arg, 1); /* Put it in RAW: mode */
if (res == 0) {
errno = ENXIO;
return (-1);
}
return (0);
}
/*
* Function - cooked() this function returns the designate file pointer to
* it's normal, wait for a <CR> mode. This is exactly like raw() except that
* it sends a 0 to the console to make it back into a CON: from a RAW:
*/
long
cooked(fp)
FILE *fp;
{
struct MsgPort *mp; /* The File Handle message port */
struct FileHandle *afh;
struct UFB *ufb;
long Arg[1], res;
ufb = (struct UFB *) chkufb(fileno(fp));
afh = (struct FileHandle *) (ufb->ufbfh);
if (!IsInteractive(afh)) {
errno = ENOTTY;
return (-1);
}
mp = ((struct FileHandle *) (BADDR(afh)))->fh_Type;
Arg[0] = 0;
res = SendPacket(mp, ACTION_SCREEN_MODE, Arg, 1);
if (res == 0) {
errno = ENXIO;
return (-1);
}
return (0);
}
SHAR_EOF
# End of shell archive
exit 0
--
Bob Page, U of Lowell CS Dept. page@swan.ulowell.edu ulowell!page
Have five nice days.